# coding : UTF-8
"""
作者：BingBO   时间：2022年10月09日
自动调整代码格式 ：Alt+Ctrl+L
"""
# coding : UTF-8
# 作者：BingBO   时间：2022年10月17日

import cv2 as cv
import numpy as np
import math
from matplotlib import pyplot as plt

#
# 灰度重心法提取激光条纹重心函数
def COG(img):
    print("input img.shape: ", img.shape)
    height, width, channels = img.shape
    b, g, r = cv.split(img)

    ret1, th1 = cv.threshold(r, 190, 255, cv.THRESH_BINARY)  # ret1分割阈值
    th1 = cv.medianBlur(th1, 3)  # 中值滤波
    # cv.imshow('threshold img', th1)

    cp_row, cp_col, Zero_col = [], [], []
    for j in range(width):  # 遍历每一列
        x0, y0 = 0, 0
        for i in range(height):  # 遍历每一行
            x0 += th1[i, j]
            y0 += th1[i, j] * (i + 1)
        if x0 != 0:
            x0_float, y0_float = float(x0), float(y0)  # 整数相除，小数直接抛弃
            point_row = round(y0_float / x0_float) - 1  #
            # 列表存储条纹中心坐标
            cp_row += [point_row]
            cp_col += [j]  # 中心点列索引列表(包含空白区域列坐标的突变)
        else:
            Zero_col += [j]  # 缺陷点的列索引(包括了交叉光条右侧 的缺少光条空白区域)

    # print("CP_row:", cp_row)
    # print("CP_col:", cp_col)
    # print("Zero_col:", Zero_col)

    # 创建新图像，显示中心点
    cpImg = np.zeros_like(img)
    for i in range(0, len(cp_row)):
        img[cp_row[i], cp_col[i]] = [255, 0, 0]  # 蓝色点显示
        cpImg[cp_row[i], cp_col[i]] = [255, 255, 255]
    cv.imshow("centralPointImg:", cpImg)

    gapNums = []
    count = 0
    T = 20
    for i in range(0, len(cp_col) - 1):  # 中心点的列总数len(CP_col)，索引是0~len(CP_col)-1，下语句后面减去前面，需再减1
        if (cp_col[i + 1] - cp_col[i]) > T:  # 中心点列坐标的突变超过阈值50，认为是边缘大断点处，排除偶尔光条的间断
            # 在原图像上标记左右两断点
            img[cp_row[i], cp_col[i]] = [0, 255, 0]
            img[cp_row[i + 1], cp_col[i + 1]] = [0, 255, 0]
            # (左断点(含中心点)列坐标 , 右断点(含中心点)列坐标 , 左右断点间距)
            gapNums.append((cp_col[i], cp_col[i + 1], (cp_col[i + 1] - cp_col[i] - 1)))
            index = i  # 断裂处的列索引
            count += 1
    # 在原输入图像上显示断点
    # cv.imshow('BreakPoint_V', img)
    print("共发现间距大于%d像素的(竖直方向)间断数：" % T, count)
    print("gapNums Info:", gapNums)

    # *************取断点左边点集****************
    cpLeft_row = cp_row[:index + 1]
    cpLeft_col = cp_col[:index + 1]

    for i, gapNum in enumerate(gapNums, start=1):
        print("列索引%d(左断点列坐标 , 右断点列坐标，断点间距): " % i, gapNum)

    return cpImg, cpLeft_row, cpLeft_col


# 计算各个点的斜率，找出3个特征点
def SlopeAnalysis(img, cpLeft_row, cpLeft_col):
    print("\n**********************SlopeAnalysis**********************")
    rank = 4
    slopeList = []
    cpNum = len(cpLeft_col)
    print("cpNum:", cpNum)
    for i in range(0, cpNum):  # 遍历列
        sum_k = 0
        if 0 <= i <= (rank - 1) or (cpNum - 4) <= i <= (cpNum - 2):
            slope = cpLeft_row[i + 1] - cpLeft_row[i]
            slopeList.append([i, slope])
        elif i == cpNum - 1:
            slope = 1
            slopeList.append([i, slope])
        else:
            for j in range(1, rank + 1):
                k = (cpLeft_row[i + j] - cpLeft_row[i - j]) / (2 * j)
                sum_k += k
            slope = sum_k / rank
            slopeList.append([i, slope])
    print("slopeList:", slopeList)
    print("len(slopeList):", len(slopeList))
    print(slopeList[:][1])
    print(np.array(slopeList)[:, 1:])
    # index = np.argmax(np.array(slopeList)[:, 1:])  # numpy数组中最大值的索引值
    index = np.argmin(np.array(slopeList)[:, 1:])
    print("最大值索引：", index)
    img[cpLeft_row[index], cpLeft_col[index]] = [0, 0, 255]
    cv.imshow("max", img)
    plt.plot(np.array(slopeList)[:, 1:])
    plt.show()


src = cv.imread(r"D:\SHU\Research Group\LaserVisionSensor\LaserImage\MVS_Data\20220909\V\Image_20220909111906812.jpg")
src = cv.resize(src, None, fx=0.4, fy=0.4, interpolation=cv.INTER_CUBIC)

cpImg, cpLeft_row, cpLeft_col = COG(src)
SlopeAnalysis(cpImg, cpLeft_row, cpLeft_col)

cv.waitKey(0)
cv.destroyAllWindows()
